package org.springblade.tms.module.transportorder.base;

import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.logging.log4j.util.Strings;
import org.springblade.common.utils.EnumUtils;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.tms.global.enums.*;
import org.springblade.tms.module.demandorder.entity.TMDemandOrder;
import org.springblade.tms.module.demandorder.service.IDemandOrderService;
import org.springblade.tms.module.exceptionreason.entity.TMExceptionReason;
import org.springblade.tms.module.exceptionreason.service.IExceptionReasonService;
import org.springblade.tms.module.exceptionrecord.dto.TMExceptionRecordDTO;
import org.springblade.tms.module.exceptionrecord.service.IExceptionRecordService;
import org.springblade.tms.module.exceptiontype.entity.TMExceptionType;
import org.springblade.tms.module.exceptiontype.service.IExceptionTypeService;
import org.springblade.tms.module.gps.base.GPSRequestService;
import org.springblade.tms.module.gps.dto.GPSWaybillStatusChangeDTO;
import org.springblade.tms.module.sap.base.SapRequestService;
import org.springblade.tms.module.sap.dto.WaybillEventDTO;
import org.springblade.tms.module.statementorder.entity.TMStatementOrder;
import org.springblade.tms.module.statementorder.service.IStatementOrderService;
import org.springblade.tms.module.transportorder.dto.TMTransportOrderDTO;
import org.springblade.tms.module.transportorder.entity.TMTransportOrder;
import org.springblade.tms.module.transportorder.service.ITransportOrderService;
import org.springblade.tms.module.transportorder.vo.TMTransportOrderVO;
import org.springblade.tms.module.transportorder.wrapper.TransportOrderWrapper;
import org.springblade.tms.module.transportorderitem.entity.TMTransportOrderItem;
import org.springblade.tms.module.transportorderitem.service.ITransportOrderItemService;
import org.springblade.tms.module.userinfo.entity.TMUserInfo;
import org.springblade.tms.module.userinfo.service.IUserInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.springblade.tms.global.constant.GPSConSigName.CONSIG_NAME;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.module.transportorder.base
 * @className: WaybillService
 * @author: yr
 * @description: 运单服务
 * @date: 2022/3/16 13:38
 */
@Service
@Transactional
public class WaybillService {
    @Resource
    private IUserInfoService userInfoService;
    @Resource
    private ITransportOrderService transportOrderService;
    @Resource
    private ITransportOrderItemService transportOrderItemService;
    @Resource
    private IExceptionRecordService exceptionRecordService;
    @Resource
    private SapRequestService sapRequestService;
    @Resource
    private IExceptionReasonService exceptionReasonService;
    @Resource
    private IExceptionTypeService exceptionTypeService;
    @Resource
    private IDemandOrderService demandOrderService;
    @Resource
    private GPSRequestService gpsRequestService;
    @Resource
    private IStatementOrderService statementOrderService;

    /**
     * @param transportOrderDTO:
     * @param query:
     * @return R<IPage < TMTransportOrderVO>>
     * @author yr
     * @description 小程序运单查询
     * @date 2022/3/16 13:56
     */
    public R<IPage<TMTransportOrderVO>> list(TMTransportOrderDTO transportOrderDTO, Query query) {
        TMTransportOrder tmTransportOrder = BeanUtil.copy(transportOrderDTO, TMTransportOrder.class);
        Long userId = AuthUtil.getUser().getUserId();
        TMUserInfo tmUserInfo = userInfoService.lambdaQuery().eq(TMUserInfo::getParentId, userId).one();
        if (tmUserInfo == null) {
            tmUserInfo = new TMUserInfo();
            tmUserInfo.setUserType(UserTypeEnum.ADMIN.getValue());
        }
        IPage<TMTransportOrder> page = transportOrderService.page(Condition.getPage(query), Condition.getQueryWrapper(new TMTransportOrder()).lambda()
                .like(tmTransportOrder.getTransportNo() != null && !tmTransportOrder.getTransportNo().isEmpty(), TMTransportOrder::getTransportNo, tmTransportOrder.getTransportNo())
                .eq(tmUserInfo != null && tmUserInfo.getUserType().equals(UserTypeEnum.CARRIER.getValue()), TMTransportOrder::getCarrierId, tmUserInfo.getId())
                .eq(tmUserInfo != null && tmUserInfo.getUserType().equals(UserTypeEnum.CHAUFFEUR.getValue()), TMTransportOrder::getDriverId, tmUserInfo.getId())
                .eq(Strings.isNotBlank(transportOrderDTO.getTransportStatus()), TMTransportOrder::getTransportStatus, transportOrderDTO.getTransportStatus())
                .orderByDesc(TMTransportOrder::getCreateTime, TMTransportOrder::getId));
        IPage<TMTransportOrderVO> pageVO = TransportOrderWrapper.build().pageVO(page);
        List<Long> ids = pageVO.getRecords().stream().map(TMTransportOrder::getId).collect(Collectors.toList());
        Map<Long, List<TMTransportOrderItem>> transportOrderItemMap = transportOrderItemService.lambdaQuery().in(!ids.isEmpty(), TMTransportOrderItem::getParentId, ids).list().stream().collect(Collectors.groupingBy(TMTransportOrderItem::getParentId));
        pageVO.getRecords().forEach(record -> {
            if (Strings.isNotBlank(record.getTankType())) {
                record.setTankType(EnumUtils.getEnumByValue(TankTypeEnum.class, record.getTankType()).get().description());
            }
            record.setSourceLocationStreet(new StringBuilder(record.getStartLocationArea())
                    .append(record.getStartLocationCity()).append(record.getStartLocationStreet()).toString());
            record.setDestinationStreet(new StringBuilder(record.getTargetLocationArea())
                    .append(record.getTargetLocationCity()).append(record.getTargetLocationStreet()).toString());
            transportOrderItemMap.get(record.getId()).forEach(item -> {
                record.setMaterialInformation(new StringBuilder(record.getMaterialInformation()).append(item.getMatDesc())
                        .append("*").append(item.getNum().toString()).append("(")
                        .append(item.getUnit()).append(")").toString());
            });
        });
        return R.data(pageVO);
    }

    /**
     * @param exceptionRecordDTO:
     * @return void
     * @author yr
     * @description 异常汇报
     * @date 2022/3/21 17:48
     */
    public R<Boolean> exceptionReport(TMExceptionRecordDTO exceptionRecordDTO) {
        if (exceptionRecordDTO.getOrderType().equals(OrderTypeEnum.SINGLE_TRANSPORT.value())) {
            exceptionRecordDTO.setExceptionDate(LocalDateTime.now());
            boolean save = exceptionRecordService.save(exceptionRecordDTO);
            TMTransportOrder tmTransportOrder = transportOrderService.lambdaQuery().eq(TMTransportOrder::getId, exceptionRecordDTO.getParentId()).one();
            WaybillEventDTO waybillEventDTO = new WaybillEventDTO();
            BeanUtil.copyNonNull(exceptionRecordDTO, waybillEventDTO);
            BeanUtil.copyNonNull(tmTransportOrder, waybillEventDTO);
            waybillEventDTO.setExceptionRemark(exceptionRecordDTO.getRemark());
            TMExceptionType tmExceptionType = exceptionTypeService.getById(exceptionRecordDTO.getExceptionType());
            waybillEventDTO.setExceptionType(tmExceptionType.getEventReasonCode());
            waybillEventDTO.setType(exceptionRecordDTO.getOrderType());
            waybillEventDTO.setEventCode(EventCodeEnum.ExceptionReport.getValue());
            waybillEventDTO.setTorId(tmTransportOrder.getOrderNoNew());
            TMExceptionReason tmExceptionReason = exceptionReasonService.getById(exceptionRecordDTO.getExceptionTypeDesc());
            waybillEventDTO.setEventReasonCode(tmExceptionReason.getReasonCode());
            sapRequestService.pushTmForUpdateWaybill(waybillEventDTO);
            return R.status(save);
        } else {
            exceptionRecordDTO.setExceptionDate(LocalDateTime.now());
            boolean save = exceptionRecordService.save(exceptionRecordDTO);
            TMDemandOrder tmDemandOrder = demandOrderService.lambdaQuery().eq(TMDemandOrder::getId, exceptionRecordDTO.getParentId()).one();
            WaybillEventDTO waybillEventDTO = new WaybillEventDTO();
            BeanUtil.copyNonNull(exceptionRecordDTO, waybillEventDTO);
            BeanUtil.copyNonNull(tmDemandOrder, waybillEventDTO);
            waybillEventDTO.setExceptionRemark(exceptionRecordDTO.getRemark());
            TMExceptionType tmExceptionType = exceptionTypeService.getById(exceptionRecordDTO.getExceptionType());
            waybillEventDTO.setExceptionType(tmExceptionType.getEventReasonCode());
            waybillEventDTO.setTorId(tmDemandOrder.getOrderNo());
            waybillEventDTO.setType(exceptionRecordDTO.getOrderType());
            waybillEventDTO.setEventCode(EventCodeEnum.ExceptionReport.getValue());
            TMExceptionReason tmExceptionReason = exceptionReasonService.getById(exceptionRecordDTO.getExceptionTypeDesc());
            waybillEventDTO.setEventReasonCode(tmExceptionReason.getReasonCode());
            sapRequestService.pushTmForUpdateWaybill(waybillEventDTO);
            return R.status(save);
        }
    }

    /**
     * @param id:
     * @return R
     * @author yr
     * @description 运输单作废
     * @date 2022/8/22 14:46
     */
    public R invalid(Long id, String reasonForVoiding) {
        TMTransportOrder tmTransportOrder = transportOrderService.getById(id);
        tmTransportOrder.setTransportStatus(WaybillStatusEnum.ABOLISHED.value());
        tmTransportOrder.setReasonForVoiding(reasonForVoiding);
//        gpsRequestService.waybillStatusChange(new GPSWaybillStatusChangeDTO(CONSIG_NAME, tmTransportOrder.getTransportNo(), "2"));
        List<TMStatementOrder> list = statementOrderService.lambdaQuery().eq(TMStatementOrder::getParentId, tmTransportOrder.getId()).list();
        if (!list.isEmpty()) {
            statementOrderService.deleteLogic(list.stream().map(TMStatementOrder::getId).collect(Collectors.toList()));
        }
        WaybillEventDTO waybillEventDTO = new WaybillEventDTO();
        BeanUtil.copyNonNull(tmTransportOrder, waybillEventDTO);
        waybillEventDTO.setType(SapTransportActionEnum.TRANSPORT.value());
        waybillEventDTO.setEventTime(LocalDateTime.now());
        waybillEventDTO.setTorId(tmTransportOrder.getOrderNo());
        waybillEventDTO.setCancel("x");
        sapRequestService.pushTmForUpdateWaybill(waybillEventDTO);
        return R.status(transportOrderService.updateById(tmTransportOrder));
    }
}
